package com.lkl.hystrixdemo.order.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.List;

@Service
public class RedisService {
    @Autowired
    StringRedisTemplate stringRedisTemplate;

    private static final String LOCK = "LOCK";

    @Autowired
    RedisTemplate redisTemplate;

    public void set(String key, String value, Long expiredTime) {
        //获取事务权限
        stringRedisTemplate.setEnableTransactionSupport(true);
        //开启事务
        stringRedisTemplate.multi();
        try {
            stringRedisTemplate.opsForValue().set(key, value, expiredTime);
            //提交事务
            stringRedisTemplate.exec();
        }catch (Exception e) {
            //回顾事务
            stringRedisTemplate.discard();
        }
    }

    public Object getKey(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }

    /**
     * lua脚本：key相等时判断value值是否相等，相等的话则删除
     */
    private static final String LUA_UNLOCK_SCRIPT = "if redis.call(\"get\",KEYS[1]) == ARGV[1] " +
            "then " +
            "return redis.call(\"del\",KEYS[1]) " +
            "else " +
            "return 0 " +
            "end";
    /**
     * 调用Lua脚本删除key
     *
     * @param keys
     * @param args
     * @return
     */
    public boolean delate(List<String> keys, List<String> args) {
        Object result = stringRedisTemplate.execute((RedisCallback<Object>) connection -> {
            Object nativeConnection = connection.getNativeConnection();

            /*if (nativeConnection instanceof RedisProperties.Jedis) {
                return ((RedisProperties.Jedis) nativeConnection).eval(LUA_UNLOCK_SCRIPT, keys, args);
            }*/
            /*//如果时redis集群
            else if (nativeConnection instanceof JedisCluster) {
                return ((JedisCluster) nativeConnection).eval(LUA_UNLOCK_SCRIPT, keys, args);
            }*/
            return 0L;
        });

        return result != null && Long.parseLong(result.toString()) > 0;
    }

    /**
     *
     * 比如，我放在redis里面2秒，业务需要处理四秒，就会添加续命锁
     * 设置一个值，如果相等话，才会删除
     * @param value
     * @return
     */
    public boolean getLock(String value) {
        boolean isLock = stringRedisTemplate.opsForValue().setIfAbsent(LOCK, value, Duration.of(2, ChronoUnit.SECONDS));
        //System.out.println(Thread.currentThread().getName() + ",开始加锁了：" + isLock);
        return isLock;
    }

    /**
     * 先检测存的值，是否相等，相等再删。
     * 可以用lua脚本保证原子性
     * @param value
     * @return
     */
    public boolean releaseLock(String value) {
        Object val = getKey(LOCK);
        System.out.println(Thread.currentThread().getName() + "，开始释放锁了, " + val);

        if (val == null) {
            return true;
        }
        if (value.equals(val.toString())) {
            return stringRedisTemplate.delete(LOCK);
        }
        return false;
    }

    public boolean remove(String key) {
        return redisTemplate.delete(key);
    }

}
